﻿using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;

namespace Nirvana
{
    [ExecuteInEditMode]
    [RequireComponent(typeof(RawImage))]
    public class UIRawImageLoad : MonoBehaviour
    {
        private sealed class RawImageBind
        {
            public AssetID assetid;
            public UIRawImageLoad rawImageLoad;
            public void Load(Texture texture)
            {
                if (rawImageLoad._rawimage == null)
                {
                    Singleton<TexturePool>.Instance.Free(texture, false);
                    return;
                }
                this.rawImageLoad._texture = texture;
                if (this.rawImageLoad._texture == null)
                {
                    string text = string.Format("Load raw texture {0} failed.", this.assetid);
                    Debug.LogError(text, this.rawImageLoad.gameObject);
                }
                if (this.rawImageLoad.assetid.Equals(this.assetid))
                {
                    this.rawImageLoad._rawimage.texture = texture;
                    if (this.rawImageLoad.autoFitNativeSize)
                    {
                        this.rawImageLoad._rawimage.SetNativeSize();
                    }
                    if (this.rawImageLoad.autoUpdateAspectRatio)
                    {
                        AspectRatioFitter aspect = this.rawImageLoad._rawimage.GetComponent<AspectRatioFitter>();
                        if (aspect != null)
                        {
                            aspect.aspectRatio = this.rawImageLoad._texture.width * 1f / this.rawImageLoad._texture.height;
                        }
                    }
                    this.rawImageLoad.Init();
                }
            }
        }


        [SerializeField]
        [Tooltip("The raw image asset.")]
        private AssetID asset;

        [Tooltip("The default texture when the asset is not loaded.")]
        [SerializeField]
        private Texture defaultTexture;

        [SerializeField]
        private bool autoFitNativeSize;

        [SerializeField]
        private bool autoUpdateAspectRatio;

        [SerializeField]
        private bool isSync = true;

        private AssetID assetid;
        private Texture _texture;
        private RawImage _rawimage;
        private bool isNeedUpdate = true;
        public bool AutoFitNativeSize
        {
            get
            {
                return this.autoFitNativeSize;
            }
            set
            {
                this.autoFitNativeSize = value;
            }
        }

        public bool AutoUpdateAspectRatio
        {
            get
            {
                return this.autoUpdateAspectRatio;
            }
            set
            {
                this.autoUpdateAspectRatio = value;
            }
        }

        public AssetID Asset
        {
            get
            {
                return this.asset;
            }
            set
            {
                if (!this.asset.Equals(value))
                {
                    this.asset = value;
                    this.isNeedUpdate = true;
                }
            }
        }

        void Awake()
        {
            this._rawimage = GetComponent<RawImage>();
            this.Load(this.assetid);
            this.Init();

        }

        private void OnGUI()
        {
            if (GUILayout.Button("Click"))
            {
                Destroy(this.gameObject);
            }
        }

        void Update()
        {
            if (this.isNeedUpdate)
            {
                this.isNeedUpdate = false;
                if (!this.assetid.Equals(this.asset))
                {
                    this.Load(asset);
                }
            }
        }

#if UNITY_EDITOR
        void OnValidate()
        {
            if (isActiveAndEnabled)
            {
                this.Init();
                this.Load(this.asset);
            }
        }
#endif

        void OnDestroy()
        {
            if (this._rawimage != null) this._rawimage.texture = null;
            if(this._texture != null)
            {
                if (Application.isPlaying)
                {
                    Singleton<TexturePool>.Instance.Free(this._texture, false);
                }
                this._texture = null;
            }
        }


        private void Load(AssetID assetID)
        {
            if (assetid.Equals(assetID))
            {
                this.Init();
                return;
            }
            if(this._texture != null)
            {
                if (Application.isPlaying)
                {
                    Singleton<TexturePool>.Instance.Free(this._texture, false);
                }
                this._texture = null;
            }
            this.assetid = assetID;
            if (assetid.IsEmpty)
            {
                this._rawimage.texture = null;
                this.Init();
                return;
            }
            if (Application.isPlaying)
                StartLoad(assetID);
            else
                StartLoad2(assetID);
        }

        private void StartLoad(AssetID asset)
        {
            RawImageBind binds = new RawImageBind();
            binds.assetid = asset;
            binds.rawImageLoad = this;
            Singleton<TexturePool>.Instance.Load(asset, binds.Load, this.isSync);
        }

        private void StartLoad2(AssetID asset)
        {
            var obj = asset.LoadObject<UnityEngine.Object>();
            if(obj != null)
            {
                this._texture = obj as Texture;
                if(this._texture == null)
                {
                    TextAsset txtAsset = obj as TextAsset;
                    if(txtAsset != null)
                    {
                        this._texture = this.LoadTexture(txtAsset);
                        Resources.UnloadAsset(txtAsset);
                    }
                }
            }

            if(this._texture != null && this.assetid.Equals(asset))
            {
                this._rawimage.texture = this._texture;
                if (this.autoFitNativeSize) this._rawimage.SetNativeSize();
                if (AutoUpdateAspectRatio)
                {
                    AspectRatioFitter component = this._rawimage.GetComponent<AspectRatioFitter>();
                    if (component != null)
                    {
                        component.aspectRatio = _texture.width*1f / _texture.height;
                    }
                }
                this.Init();
            }

        }

        private void Init()
        {
            if(this._texture == null)
            {
                if(this.defaultTexture != null)
                {
                    this._rawimage.enabled = true;
                    this._rawimage.texture = this.defaultTexture;
                }
                else
                {
                    this._rawimage.enabled = false;
                }
            }
            else
            {
                this._rawimage.enabled = true;
            }
        }

        private Texture2D LoadTexture(TextAsset textAsset)
        {
            byte[] bytes = textAsset.bytes;
            var format = TextureFormat.RGBA32;
            if (bytes != null && bytes[1] == 80 && bytes[2] == 78 && bytes[3] == 71)
            {
                format = TextureFormat.RGBA32;
            }

            var texture2D = new Texture2D(2, 2, format, false);
            if (!ImageConversion.LoadImage(texture2D, bytes, true))
            {
                return null;
            }
            texture2D.wrapMode = TextureWrapMode.Clamp;
            return texture2D;
        }



    }
}

